11. Objects¶
Note
The below information is extensively based in information taken from the PowerShell® Notes for Professionals book. I plan to extend this information based on my day to day usage of the language.
11.1: Examining an object¶
Now that you have an object, it might be good to figure out what it is. You can use the Get-Member cmdlet to see what an object is and what it contains:
1 | Get-Item c:\windows | Get-Member |
This yields:
1 | TypeName: System.IO.DirectoryInfo |
Followed by a list of properties and methods the object has.
Another way to get the type of an object is to use the GetType method, like so:
1 2 | $Object = Get-Item C:\Windows $Object.GetType() |
1 2 3 | IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True DirectoryInfo System.IO.FileSystemInfo |
To view a list of properties the object has, along with their values, you can use the Format-List cmdlet with its Property parameter set to: * (meaning all).
Here is an example, with the resulting output:
1 | Get-Item C:\Windows | Format-List -Property * |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | PSPath : Microsoft.PowerShell.Core\FileSystem::C:\Windows PSParentPath : Microsoft.PowerShell.Core\FileSystem::C:\ PSChildName : Windows PSDrive : C PSProvider : Microsoft.PowerShell.Core\FileSystem PSIsContainer : True Mode : d----- BaseName : Windows Target : {} LinkType : Name : Windows Parent : Exists : True Root : C:\ FullName : C:\Windows Extension : CreationTime : 30/10/2015 06:28:30 CreationTimeUtc : 30/10/2015 06:28:30 LastAccessTime : 16/08/2016 17:32:04 LastAccessTimeUtc : 16/08/2016 16:32:04 LastWriteTime : 16/08/2016 17:32:04 LastWriteTimeUtc : 16/08/2016 16:32:04 Attributes : Directory |
11.2: Updating Objects¶
Adding properties
If you'd like to add properties to an existing object, you can use the Add-Member cmdlet. With PSObjects, values are kept in a type of "Note Properties"
1 2 3 4 5 | $object = New-Object -TypeName PSObject -Property @{ Name = $env:username ID = 12 Address = $null } |
1 | Add-Member -InputObject $object -Name "SomeNewProp" -Value "A value" -MemberType NoteProperty |
1 2 3 4 5 | # Returns $Object Name ID Address SomeNewProp ---- -- ------- ----------- nem 12 A value |
You can also add properties with Select-Object Cmdlet (so called calculated properties):
1 | $newObject = $Object | Select-Object *, @{label='SomeOtherProp'; expression={'Another value'}} |
1 2 3 4 5 | # Returns $newObject Name ID Address SomeNewProp SomeOtherProp ---- -- ------- ----------- ------------- nem 12 A value Another value |
The command above can be shortened to this:
1 | $newObject = $Object | Select *,@{l='SomeOtherProp';e={'Another value'}} |
Removing properties
You can use the Select-Object Cmdlet to remove properties from an object:
1 | $object = $newObject | Select-Object * -ExcludeProperty ID, Address |
1 2 3 4 5 | # Returns $object Name SomeNewProp SomeOtherProp ---- ----------- ------------- nem A value Another value |
11.3: Creating a new object¶
PowerShell, unlike some other scripting languages, sends objects through the pipeline. What this means is that when you send data from one command to another, it's essential to be able to create, modify, and collect objects.
Creating an object is simple. Most objects you create will be custom objects in PowerShell, and the type to use for that is PSObject. PowerShell will also allow you to create any object you could create in .NET.
Here's an example of creating a new objects with a few properties:
Option 1: New-Object
1 2 3 4 5 | $newObject = New-Object -TypeName PSObject -Property @{ Name = $env:username ID = 12 Address = $null } |
1 2 3 4 5 | # Returns $newObject Name ID Address ---- -- ------- nem 12 |
You can store the object in a variable by prefacing the command with $newObject =
You may also need to store collections of objects. This can be done by creating an empty collection variable, and adding objects to the collection, like so:
1 2 3 4 5 6 | $newCollection = @() $newCollection += New-Object -TypeName PSObject -Property @{ Name = $env:username ID = 12 Address = $null } |
You may then wish to iterate through this collection object by object. To do that, locate the Loop in the documentation.
Option 2: Select-Object
A less common way of creating objects that you'll still find on the internet is the following:
1 2 3 | $newObject = 'unuseddummy' | Select-Object -Property Name, ID, Address $newObject.Name = $env:username $newObject.ID = 12 |
1 2 3 4 5 | # Returns $newObject Name ID Address ---- -- ------- nem 12 |
Option 3: pscustomobject type accelerator (PSv3+ required)
The ordered type accelerator forces PowerShell to keep our properties in the order that we defined them. You don't need the ordered type accelerator to use [PSCustomObject]:
1 2 3 4 5 | $newObject = [PSCustomObject][Ordered]@{ Name = $env:Username ID = 12 Address = $null } |
1 2 3 4 5 | # Returns $newObject Name ID Address ---- -- ------- nem 12 |
11.4: Creating Instances of Generic Classes¶
Note: examples written for PowerShell 5.1 You can create instances of Generic Classes
1 2 3 4 5 6 7 8 9 10 11 12 | #Nullable System.DateTime [Nullable[datetime]]$nullableDate = Get-Date -Year 2012 $nullableDate $nullableDate.GetType().FullName $nullableDate = $null $nullableDate #Normal System.DateTime [datetime]$aDate = Get-Date -Year 2013 $aDate $aDate.GetType().FullName $aDate = $null #Throws exception when PowerShell attempts to convert null to |
Gives the output:
1 2 3 4 5 6 7 8 9 10 | Saturday, 4 August 2012 08:53:02 System.DateTime Sunday, 4 August 2013 08:53:02 System.DateTime Cannot convert null to type "System.DateTime". At line:14 char:1 + $aDate = $null + ~~~~~~~~~~~~~~ + CategoryInfo : MetadataError: (:) [], ArgumentTransformationMetadataException + FullyQualifiedErrorId : RuntimeException |
Generic Collections are also possible
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | [System.Collections.Generic.SortedDictionary[int, String]]$dict = [System.Collections.Generic.SortedDictionary[int, String]]::new() $dict.GetType().FullName $dict.Add( 1 , 'a') $dict.Add( 2 , 'b') $dict.Add( 3 , 'c') $dict.Add('4', 'd') #powershell auto converts '4' to 4 $dict.Add('5.1', 'c') #powershell auto converts '5.1' to 5 $dict $dict.Add('z', 'z') #powershell can't convert 'z' to System.Int32 so it throws an error |
Gives the output:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | System.Collections.Generic.SortedDictionary`2[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] Key Value --- ----- 1 a 2 b 3 c 4 d 5 c Cannot convert argument "key", with value: "z", for "Add" to type "System.Int32": "Cannot convert value "z" to type "System.Int32". Error: "Input string was not in a correct format."" At line:15 char:1 + $dict.Add('z', 'z') #powershell can't convert 'z' to System.Int32 so ... + ~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [], MethodException + FullyQualifiedErrorId : MethodArgumentConversionInvalidCastArgument |